/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */
package td.server;

import java.util.ArrayList;
import java.util.Date;

import td.domain.Thinker;
import td.domain.Thought;
import td.domain.delta.ThoughtAdd;
import td.domain.delta.TitleChange;
import td.domain.delta.VersionAdd;
import td.domain.delta.VersionPublish;
import td.domain.util.IdCache;
import td.server.dao.ObjectifyDao;
import td.server.dao.ThinkerDao;
import td.server.dao.ThoughtDao;
import td.server.dao.ThoughtVersionDao;
import td.server.util.Validator;
import td.server.util.Versioner;
import td.shared.InvalidStateException;

import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.inject.Inject;

/**
 * A service for Thought related operations.
 * 
 * @author Artem Shamsutdinov
 * 
 */
public class ThoughtService {

	@Inject
	Validator validator;
	@Inject
	Versioner versioner;
	@Inject
	ThinkerDao thinkerDao;
	@Inject
	ThoughtDao thoughtDao;
	@Inject
	ThoughtVersionDao thoughtVersionDao;
	@Inject
	ObjectifyDao<ThoughtAdd> thoughtAddDao;
	@Inject
	ObjectifyDao<VersionAdd> versionAddDao;
	@Inject
	ObjectifyDao<TitleChange> titleChangeDao;
	@Inject
	ObjectifyDao<VersionPublish> versionPublishDao;
	@Inject
	ObjectifyDao<IdCache> idCacheDao;

	/**
	 * Adds a new thought.
	 * 
	 * @param title
	 *            Title of the new thought.
	 * @param text
	 *            Initial text of the new thought.
	 * @param thinker
	 *            Thinker to which this thought belongs to.
	 * @param publish
	 *            Publish this thought?
	 * @return The created thought.
	 * @throws EntityNotFoundException
	 */
	public Thought addThought(String title, String text, Thinker thinker,
			boolean publish) {
		return null;
		// FIXME: add this back in and figure out how to deal with Ref in GWT
		// Thought thought = new Thought();
		// thought.setTitle(title);
		// thought.setText(text);
		// thought.setThinkerId(thinker.getId());
		//
		// IdCache recentPublishedVesiontIds = new IdCache();
		// Key<IdCache> publishedVersionIdsKey = idCacheDao
		// .putNow(recentPublishedVesiontIds);
		// thought.setRecentPublishedVersionIds(Ref.create(publishedVersionIdsKey));
		// IdCache recentUnpublishedVesiontIds = new IdCache();
		// Key<IdCache> unpublishedVersionIdsKey = idCacheDao
		// .putNow(recentUnpublishedVesiontIds);
		// thought
		// .setRecentUnpublishedVersionIds(Ref.create(unpublishedVersionIdsKey));
		//
		// // Generate the ID to be used later
		// thoughtDao.putNow(thought);
		//
		// Date now = new Date();
		// Long versionId = versioner.maintainVersions(text,
		// Versioner.FIRST_VERSION_SEQUENCE, thought, thinker, publish, now,
		// null,
		// false, false);
		// createThoughtAddRecord(thought.getId(), versionId,
		// thought.getTitle(),
		// thinker.getId(), publish, now);
		// return thought;
	}

	private void createThoughtAddRecord(Long thoughtId, Long thoughtVersionId,
			String title, Long thinkerId, boolean publish, Date dateAdded) {
		ThoughtAdd thoughtAddRecord = new ThoughtAdd(thoughtId,
				thoughtVersionId, title, thinkerId, publish, dateAdded);
		thoughtAddDao.put(thoughtAddRecord);
	}

	/**
	 * Changes the title of the thought. Only unpublished thoughts can have
	 * their title changed.
	 * 
	 * @param thinker
	 *            Thinker to which this thought belongs to.
	 * @param thought
	 *            The thought being modified.
	 * @param title
	 *            New title of this thought.
	 * @throws InvalidStateException
	 */
	public void changeTitle(Thinker thinker, Thought thought, String title)
			throws InvalidStateException {
		validator.validateUnpublishedThought(thinker, thought);

		Date now = new Date();
		thought.setTitle(title);
		thought.setLastUpdatedDate(now);

		thoughtDao.put(thought);

		TitleChange titleChangeRecord = new TitleChange(thought.getId(), title,
				thinker.getId(), now);
		titleChangeDao.put(titleChangeRecord);
	}

	/**
	 * Gets a page of thoughts.
	 * 
	 * @param thinker
	 *            (retrieved by thinker)
	 * @param pageSize
	 *            Number of thoughts in this page.
	 * @param pageNumber
	 *            The number of thoughts.
	 * @param published
	 *            What thoughts to return (published vs. unpublished)
	 * @return ArrayList (and not List) because of GWT serialization
	 */
	public ArrayList<Thought> getPageOfRecentThoughts(Thinker thinker,
			int pageSize, int pageNumber, boolean published, Thinker requestor) {
		// TODO Auto-generated method stub
		return null;
	}

	// private void findThoughts(Thinker thinker, Cursor cursor) {
	// long startTime = System.currentTimeMillis();
	//
	// thoughtDao.listByProperties("droppedOffLists", true, "thinkerId",
	// thinker.getId());
	// Query<Thought> query = ofy.query(Thought.class);
	//
	// String cursorStr = request.getParameter("cursor");
	// if (cursorStr != null)
	// query.startCursor(Cursor.fromWebSafeString(cursorStr));
	//
	// QueryResultIterator<Car> iterator = query.iterator();
	// while (iterator.hasNext()) {
	// Car car = iterator.next();
	//
	// ... // process car
	//
	// if (System.currentTimeMillis() - startTime > LIMIT_MILLIS) {
	// Cursor cursor = iterator.getStartCursor();
	// Queue queue = QueueFactory.getDefaultQueue();
	// queue.add(url("/pathToThisServlet").param("cursor",
	// cursor.toWebSafeString()));
	// break;
	// }
	// }
	// }
}
